﻿Imports WPFGlue.Framework
Imports System.Windows.Controls.Primitives

Public Class StickyTestComponent
    Inherits DependencyObject
    Implements INamedStickyComponent

    Private _Name As String = "[not yet set]"
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
            Debug.Print("Named {0} #{2} {1}", Me.GetType.Name, Name, _Index)
        End Set
    End Property

    Public Shared ReadOnly ComponentProperty As DependencyProperty = _
        DependencyProperty.RegisterAttached("Component", _
        GetType(IStickyComponent), GetType(StickyTestComponent), _
        New PropertyMetadata(AddressOf StickyComponentManager.OnStickyComponentChanged))
    Public Shared Function GetComponent(ByVal d As DependencyObject) As IStickyComponent
        Return d.GetValue(ComponentProperty)
    End Function
    Public Shared Sub SetComponent(ByVal d As DependencyObject, _
                                   ByVal value As IStickyComponent)
        d.SetValue(ComponentProperty, value)
    End Sub

    Private _Mode As AttachMode = AttachMode.Immediate
    Public Property AttachMode() As AttachMode
        Get
            Return _Mode
        End Get
        Set(ByVal value As AttachMode)
            _Mode = value
        End Set
    End Property
    Private ReadOnly Property Mode() As AttachMode Implements IStickyComponent.Mode
        Get
            Return _Mode
        End Get
    End Property

    Public Sub OnAttach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnAttach
        Debug.Print("{0} {1} Attached, that's #{2}", Me.GetType.Name, Name, _Index)
    End Sub

    Public Sub OnDetach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnDetach
        Debug.Print("{0} {1} Detached, that's #{2}", Me.GetType.Name, Name, _Index)
    End Sub

    Private ReadOnly Property PrivateName() As String Implements INamedStickyComponent.Name
        Get
            Return _Name
        End Get
    End Property

    Private Shared _Count As Integer = 0
    Private _Index As Integer
    Public Sub New()
        MyBase.New()
        _Count += 1
        _Index = _Count
        Debug.Print("{0} {1} Constructed, that's #{2}", Me.GetType.Name, Name, _Index)
    End Sub
    Protected Overrides Sub Finalize()
        Debug.Print("{0} {1} Finalized, that's #{2}", Me.GetType.Name, Name, _Index)
        MyBase.Finalize()
    End Sub

End Class

Public Class StickyTestComponentSet
    Inherits StickyComponentCollection(Of StickyTestComponent)
    Implements IStickyComponent, IList

    Public Sub OnAttach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnAttach
        Debug.Print("{0} {1} Attached", Me.GetType.Name, _Index)
        MyBase.OnAttach(sender, e)
    End Sub

    Public Sub OnDetach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnDetach
        Debug.Print("{0} {1} Detached", Me.GetType.Name, _Index)
        MyBase.OnDetach(sender, e)
    End Sub

    Private Shared _Count As Integer = 0
    Private _Index As Integer
    Public Sub New()
        MyBase.New()
        _Count += 1
        _Index = _Count
        Debug.Print("{0} {1} Constructed", Me.GetType.Name, _Index)
    End Sub
    Protected Overrides Sub Finalize()
        Debug.Print("{0} {1} Finalized", Me.GetType.Name, _Index)
        MyBase.Finalize()
    End Sub
End Class

Public Class TestStickyPatterns
    Inherits StickyTestComponent
    Implements IStickyComponent

    Public Shared ReadOnly MyCommand As New RoutedCommand

    Private _UseCommand As Boolean = False
    Public Property UseCommand() As Boolean
        Get
            Return _UseCommand
        End Get
        Set(ByVal value As Boolean)
            _UseCommand = value
        End Set
    End Property

    Public Sub OnAttach(ByVal base As Object, ByVal e As EventArgs) Implements IStickyComponent.OnAttach
        MyBase.OnAttach(base, e)
        If _UseCommand Then
            StickyComponentManager.Attach(base, MyCommand, AddressOf OnExecuted, Nothing)
            StickyComponentManager.Attach(base, New KeyGesture(Key.Space, ModifierKeys.Control), MyCommand)
        Else
            StickyComponentManager.Attach(base, ButtonBase.ClickEvent, AddressOf OnClick)
            StickyComponentManager.Attach(base, ButtonBase.ClickEvent, AddressOf OnClickOneShot, True)
            StickyComponentManager.Attach(base, ButtonBase.ClickEvent, AddressOf OnClickCancel, FocusManager.LostFocusEvent)
        End If
    End Sub

    Public Sub OnDetach(ByVal base As Object, ByVal e As EventArgs) Implements IStickyComponent.OnDetach
        MyBase.OnDetach(base, e)
        If _UseCommand Then
            StickyComponentManager.Detach(base, New KeyGesture(Key.Space, ModifierKeys.Control))
            StickyComponentManager.Detach(base, MyCommand)
        Else
            StickyComponentManager.Detach(base, ButtonBase.ClickEvent, AddressOf OnClick)
            StickyComponentManager.Detach(base, ButtonBase.ClickEvent, AddressOf OnClickOneShot)
            StickyComponentManager.Detach(base, ButtonBase.ClickEvent, AddressOf OnClickCancel)
        End If
    End Sub

    Private Sub OnClickOneShot(ByVal sender As Object, ByVal e As RoutedEventArgs)
        MsgBox("This is the OneShot Click event. You should see this only once.")
    End Sub

    Private Sub OnClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
        MsgBox("This is the Click event. You should see this every time.")
    End Sub

    Private Sub OnClickCancel(ByVal sender As Object, ByVal e As RoutedEventArgs)
        MsgBox("This is the One Shot event with CancelEvent handlers. You should see this only once, but not if you have moved focus away from the button before.")
    End Sub

    Private Sub OnExecuted(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
        MsgBox("Executed the Command")
    End Sub

End Class